;;; Code:
(require 'autorevert)
(require 'epa-file)
(require 'savehist)
(require 'recentf)
(require 'saveplace)
(require 'nsm)
(require 'comp)
(require 'async)
(require 'async-bytecomp)
(require 'browse-kill-ring)

(defcustom user-short-name ""
  "A short user name."
  :type 'string
  :group 'distopico)

(defcustom distopico:after-init-load-hook nil
  "Hook called after the `init.el' load all required dependencies."
  :type 'list
  :group 'distopico)

;; Require misc stuff
(defvar distopico:backup-dir (in-emacs-d ".cache/backup/")
  "Place backups in `~/.emacs.d/.cache/backups/' directory.")
(defvar distopico:auto-save-dir (in-emacs-d ".cache/auto-save-list/")
  "Place auto-save files in `~/.cache/auto-save-list/' directory.")
(defvar distopico:swapping-buffer nil
  "Control of swapping buffers.")
(defvar distopico:swapping-window nil
  "Control of swapping window.")

;; Basic user data
(setq user-full-name  "Distopico"
      user-mail-address "distopico@riseup.net"
      user-short-name "distopico")

;; Save custom variables in another file
(setq custom-file (in-emacs-d "custom.el"))
(load custom-file 'noerror)

;; Keep cache
;; TODO: remove this and use the default (disabled)
(setq epa-file-cache-passphrase-for-symmetric-encryption t)

;; Network
(setq nsm-settings-file (in-emacs-d ".cache/network-security.data"))
(when (boundp 'request-storage-directory)
  (setq request-storage-directory (in-emacs-d ".cache/request")))

;; Create directory if no exist
(when (and (not (file-directory-p distopico:backup-dir)))
  (make-directory distopico:backup-dir t))

;; Defined backup/auto-save directories
(setq backup-directory-alist (list (cons ".*" distopico:backup-dir))
      auto-save-list-file-prefix (concat distopico:auto-save-dir ".saves-")
      auto-save-no-message t)

;; Native compile cache
(when (functionp 'startup-redirect-eln-cache)
  (startup-redirect-eln-cache (in-emacs-d ".cache/eln-cache")))

;; Save commands history
(setq savehist-file (in-emacs-d ".cache/history"))
(savehist-mode +1)

;; Recent files and places
(setq recentf-auto-cleanup 300
      recentf-max-saved-items 300
      recentf-exclude
      (append recentf-exclude
              '("\\.emacs.d/el-get/" "~$" "\\.autosaves/"
		"\\.emacs.d/elpa/" "/.emacs.bmk$"
		"\\.ido.last" "session\\.[a-f0-9]*$"
		"\\.recentf" "/.emacs.d/TAGS"
		"\\.cache/" "\\.mail/"
		"\\.gz"))
      save-place-forget-unreadable-files nil ; no checks every loaded file is readable
      save-place-file (in-emacs-d ".cache/places"))

(recentf-mode +1)
(save-place-mode +1)
(run-with-idle-timer (* 10 60) t 'recentf-save-list)

;; Clean up the backups
(setq backup-by-copying t
      delete-old-versions t
      version-control t
      kept-new-versions 3
      kept-old-versions 2)

;; Initialize emacs server mode
;; (server-start)

;; Verify UTF-8
(setq locale-coding-system 'utf-8
      x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)

;; Allow recursive minibuffers
;; TODO: check if this is useful
(setq enable-recursive-minibuffers nil)
(minibuffer-depth-indicate-mode -1)

;; Transparently open compressed files
(auto-compression-mode t)

;; Move files to trash when deleting
(setq delete-by-moving-to-trash t)

;; Auto refresh buffers
(setq global-auto-revert-non-file-buffers t
      auto-revert-verbose nil)
(global-auto-revert-mode t)

;; Silent native compilation warnings
(setq native-comp-async-report-warnings-errors 'silent)

;; ignore byte-compile warnings
(setq byte-compile-warnings '(not nresolved
                                  free-vars
                                  callargs
                                  redefine
                                  obsolete
                                  noruntime
                                  cl-functions
                                  interactive-only))
;; Enable async byte-compile
(async-bytecomp-package-mode t)

;; Browse kill ring
(setq browse-kill-ring-highlight-current-entry t
      browse-kill-ring-show-preview t)

;; Custom functions
(defun distopico:shutdown ()
  "Shutdown Emacs server instance.
save buffers, Quit, and Shutdown (kill) server"
  (interactive)
  (save-some-buffers)
  (call-interactively #'kill-emacs))

(defun distopico:delete-old-backups ()
  "Delete backups files older than a week."
  (interactive)
  (if (file-directory-p distopico:backup-dir)
      (message "Deleting old backup files...")
    (let ((week (* 60 60 24 7))
          (current (float-time (current-time))))
      (dolist (file (directory-files distopico:backup-dir t))
        (when (and (backup-file-name-p file)
                   (> (- current (float-time (cl-fifth (file-attributes file))))
                      week))
          (message "%s" file)
          (delete-file file))))))

(defun distopico:warn-if-symlink ()
  "Progn here to execute both as part of else statement together."
  (if (file-symlink-p buffer-file-name)
      (message "File is a symlink")))

;; Advice functions
(advice-add #'recentf-save-list :around 'distopico:inhibit-outputs-advisor)
(advice-add #'recentf-cleanup :around 'distopico:inhibit-outputs-advisor)

;; Hooks
;; (add-hook 'before-save-hook 'delete-trailing-whitespace)
(add-hook 'find-file-hook 'distopico:warn-if-symlink)
(add-hook 'emacs-lisp-mode-hook 'byte-compile-when-save)

;; Prevent show my password when I'm entering.
(add-hook 'comint-output-filter-functions
          'comint-watch-for-password-prompt)

(provide 'setup-general)
